﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Windows.Forms;
using Games.Classes;
using Games.Forms.Games;

namespace Games.Forms
{
	public partial class FormMain : Form
	{
		private const int FirstButtonX = 4;
		private const int ButtonXIncrement = 75;
		private const int ButtonXPlacementMaxWidth = 1000;
		private const int FirstButtonY = 25;
		private const int ButtonYIncrement = 25;
		private const int ButtonYPlacementMaxWidth = 1000;

		private readonly List<Game> Games;
		public FormMain()
		{
			InitializeComponent();
			Games = new List<Game>()
				{
					new Game() {Name = "Snake", FormName = "FormSnake", ShortcutKey = Keys.S, FormType = typeof(FormSnake), ButtonBackColor = Color.Black, ButtonTextColor = Color.Chartreuse},
					new Game() {Name = "Miss Pac Man", FormName = "FormMsPacMan", ShortcutKey = Keys.P, FormType = typeof(FormMsPacMan), ButtonBackColor = Color.Black, ButtonTextColor = Color.Yellow},
					new Game() {Name = "Pong", FormName = "FormPong", ShortcutKey = Keys.P, FormType = typeof(FormPong), ButtonBackColor = Color.White, ButtonTextColor = Color.Black},
					new Game() {Name = "Galaga", FormName = "FormGalaga", ShortcutKey = Keys.G, FormType = typeof(FormGalaga), ButtonBackColor = Color.Blue, ButtonTextColor = Color.White}
				};
		}

		private void FormMain_Load(object sender, EventArgs e)
		{
			AddButtonsForGames(ButtonXPlacementMaxWidth, ButtonYPlacementMaxWidth);
		}

		private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			(new About()).ShowDialog();
		}

		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void FormMain_KeyPress(object sender, KeyPressEventArgs e)
		{
			if(e.KeyChar == (char)Keys.Escape)
				Close();
		}

		public static Func<object[], object> CreateConstructorDelegate(ConstructorInfo method)
		{
			var args = Expression.Parameter(typeof(object[]), "args");

			var parameters = new List<Expression>();

			var methodParameters = method.GetParameters().ToList();
			for (var i = 0; i < methodParameters.Count; i++)
			{
				parameters.Add(Expression.Convert(
													 Expression.ArrayIndex(args, Expression.Constant(i)),
													 methodParameters[i].ParameterType));
			}

			var call = Expression.Convert(Expression.New(method, parameters), typeof(object));

			Expression body = call;

			var callExpression = Expression.Lambda<Func<object[], object>>(body, args);
			var result = callExpression.Compile();

			return result;
		}

		private void AddButtonsForGames(int width, int height)
		{
			int x = FirstButtonX;
			int y = FirstButtonY;
			foreach (var game in Games)
			{
				var gameStartButton = new Button
				{
					Text = game.Name,
					Name = game.FormName,
					Location = new Point(x, y),
					BackColor = game.ButtonBackColor,
					ForeColor = game.ButtonTextColor,
				};
				if (game.ButtonImageUrl != null)
				{
					gameStartButton.ImageAlign = ContentAlignment.MiddleLeft;
					gameStartButton.Image = new Bitmap(game.ButtonImageUrl);
				}
				if (y + (ButtonYIncrement * 2) <= height/*gbGameSelection.Height*/)
				{
					y += ButtonYIncrement;
				}
				else
				{
					//no more buttons can fit in this column, move on to the next one
					if (x + (ButtonXIncrement * 2) <= width/*gbGameSelection.Width*/)
					{
						y = FirstButtonY;
						x += ButtonXIncrement;
					}
					else
					{
						// no more buttons can fit on the screen
						break;
					}
				}
				gameStartButton.Click += (sender2, args) =>
				{
					var game2 = Games.Single(g => g.FormName == ((Button)sender2).Name);
					((Form)Activator.CreateInstance(game2.FormType)).ShowDialog();
				};
				this.Controls.Add(gameStartButton);
			}
		}
	}
}
